#include <iostream>

#include "request.h"
#include "response.h"
#include "handler.h"
#include "message.h"
#include "channel.h"

#include "memory_object_pool.h"

MemoryObjectPool pool;

using namespace std;

class LocalChannel : public Channel {
public:
    bool sendMessage(const std::shared_ptr<Message> &msg) override {

        return true;
    }
};

class Client {
public:
    Client(Handler &hdl) : m_hdl(hdl) {}

    std::shared_ptr<Response> request(uint32_t id, const std::string &question, int timeout) {
        auto req = std::make_shared<Request>(timeout);
        auto msg = std::make_shared<Message>(id, "Request");
        msg->fill((uint8_t*)question.data(), question.size());
        req->setMessage(msg);
        m_hdl.request(req);
        req->wait();
        return req->result();
    }

    void request(uint32_t id, const std::string &question, const Request::OnReply &onReply) {
        auto req = std::make_shared<Request>(onReply);
        auto msg = std::make_shared<Message>(id, "Request");
        msg->fill((uint8_t*)question.data(), question.size());
        req->setMessage(msg);
        m_hdl.request(req);
    }

private:
    Handler &m_hdl;
};

int main()
{
    cout << "Hello World!" << endl;

    auto &&mo = pool.take();

    // auto mo = std::make_unique<MemoryObject>();

    // Handler hdl;
    // std::shared_ptr<LocalChannel> channel = std::make_shared<LocalChannel>();
    // hdl.setChannel(std::dynamic_pointer_cast<Channel>(channel));
    // Client clnt(hdl);

    // auto res = std::make_shared<Response>();
    // auto resmsg = std::make_shared<Message>(1, "Response");
    // res->setMessage(resmsg);
    // res->setState(Response::Ok);

    // auto thrd = std::thread([&]() {
    //     std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    //     hdl.response(std::move(res));
    // });

    // // auto &&ret = clnt.request(1, "Are you ok?", 1000);
    // // if(!ret) {
    // //     cout << "error...\n";
    // // } else if(ret->state() != Response::Ok) {
    // //     cout << "not ok... " << ret->state() << endl;
    // // } else {
    // //     cout << "ok\n";
    // // }

    // clnt.request(1, "Are you ok?", [](const std::shared_ptr<Response> &res) {
    //     if(!res) {
    //         cout << "error...\n";
    //     } else if(res->state() != Response::Ok) {
    //         cout << "not ok... " << res->state() << endl;
    //     } else {
    //         cout << "ok\n";
    //     }
    // });

    // if(thrd.joinable())
    //     thrd.join();
    // std::this_thread::sleep_for(std::chrono::milliseconds(10));
    return 0;
}
